/**
 * 
 */
package it.unical.canonaco.rende.igpe.game.cbv.guilayer.match;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.prefs.BackingStoreException;

import javax.imageio.ImageIO;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import it.unical.canonaco.rende.igpe.game.cbv.guilayer.AnimatedPanel;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.MainFrame;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.components.IsometricMatchPainter;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.components.OverallGUILayoutFactory;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.gamemanagermenu.MapAreaPanel;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.gamemanagermenu.menucomponent.PrePlayMatchPanel;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.guievents.CharacterClickEvent;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.guievents.ClickedMapCellEvent;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.guievents.GraphicEvent;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.guievents.GraphicEventListener;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.guievents.GraphicEventManager;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.match.components.CharacterInformationContainerPanel016;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.match.components.EndMatchDialog;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.match.components.TurnDialog;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.SpriteSheetCache;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.SpriteSheetInterface;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.key.AbstractSheetKey;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.MatchManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.ActionCoordinateInfo;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.filehandlers.IniLoader;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.pawn.Character;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.AttackEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EndActionEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EndMatchEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EventListener;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EventManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.GenericEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.InvalidPointSettingEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.MovementEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.NoActionEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.NotEnoughtCharacterEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.SelectedAbilityEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.SelectedCharacterEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.TurnEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.exceptions.InvalidFileException;

/**
 * @author Massimo Canonaco
 *
 */
public class MatchPanel extends AnimatedPanel implements  EventListener, GraphicEventListener
{

	static private final String CONFIGURATION_FILE = "cbvapps"+File.separatorChar+"uiresource"+File.separatorChar+"battleschema.ini";
	private MapAreaPanel mapArea;
	private IsometricMatchPainter painter;
	
//	/** */
//	private PrePlayMatchPanel parent;
	/** */
	private Character actor;
	
	/** */
	private MainFrame mainFrame;
	
	/** */
	private boolean listening;
	
	/** */
	private TurnDialog turnDialog;// = new TurnDialog(mainFrame);
	
	/** */
	private EndMatchDialog endMatchDialog;
	
	/** */
	private MatchManager matchManager;
	
	/** */
	private boolean poppedEndMatch;
	
	/** */
	private CharacterInformationContainerPanel016 characterInformationPanel;
	private RoundInformationPanel016 turnInfo;
	
	public MatchPanel(final long delay, it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.Map arena, MatchManager matchManager,MainFrame mainFrame)
	{
		super(delay,CONFIGURATION_FILE);
		this.mainFrame = mainFrame;
		poppedEndMatch = false;
//		System.out.println("!!!!! --- START MATCH PANEL --- !!!!");
		IniLoader loader = new IniLoader(new HashMap<String,String>());
		try 
		{
			this.matchManager = matchManager;
			
			GraphicEventManager.getInstance().addListener(this, CharacterClickEvent.class);
			GraphicEventManager.getInstance().addListener(this, ClickedMapCellEvent.class);

			EventManager.getInstance().addListener(this, new NotEnoughtCharacterEvent());
			EventManager.getInstance().addListener(this, new InvalidPointSettingEvent(false));
			EventManager.getInstance().addListener(this, new MovementEvent(null,0,0,0,0));
			EventManager.getInstance().addListener(this, new AttackEvent(false, false, null, null, null, 0.0f));
			EventManager.getInstance().addListener(this, new SelectedCharacterEvent(null, 0, 0, 0));
			EventManager.getInstance().addListener(this, new SelectedAbilityEvent(null, 0));
			EventManager.getInstance().addListener(this, new NoActionEvent());
			EventManager.getInstance().addListener(this, new TurnEvent());
			EventManager.getInstance().addListener(this, new EndMatchEvent(null,null));
			
			loader.load(CONFIGURATION_FILE);
			Map<String,String> settings = loader.getContents();
			SpriteSheetCache cache = new SpriteSheetCache(settings.get("avysprite")+File.separator, new HashMap<AbstractSheetKey, SpriteSheetInterface>());
//			start = System.currentTimeMillis();
			setBackground(OverallGUILayoutFactory.getInstance().getParsedColor(settings.get("matchpanel.background.color")));
			painter = new IsometricMatchPainter(cache, settings.get("matchpanel.maparea.texture.path")+File.separator+arena.getName()+File.separator+"iso"+File.separator, null,matchManager.getClientPlayer().getCharacters(), matchManager.getEnemy().getCharacters(), arena);
			painter.setting(EventManager.getInstance());
			mapArea = new MapAreaPanel(arena, settings, null, painter);
			mapArea.addMouseMotionListener(new MouseMotionListener() {
				
				@Override
				public void mouseMoved(MouseEvent arg0) 
				{
					Point punto = new Point();
					painter.coordinates(arg0.getX(), arg0.getY(), 128, punto);
					painter.getAbilityCircle().setCenterRow(punto.x);
					painter.getAbilityCircle().setCenterColumn(punto.y);
//					System.out.println("!!!! "+arg0.getX()+" "+arg0.getY()+" ---> "+punto.getX()+" "+punto.getY());
					
				}
				
				@Override
				public void mouseDragged(MouseEvent arg0) {
					// TODO Auto-generated method stub
					
				}
			});
			turnDialog = new TurnDialog(mainFrame,settings);
			mapArea.setOpaque(false);
			Dimension size = mainFrame.getSize();
			this.setSize(size);
			setMinimumSize(size);
			GridBagLayout centerPaneLayout = new GridBagLayout();
			setLayout(centerPaneLayout);

			GridBagConstraints constr = new GridBagConstraints();
			constr.anchor = GridBagConstraints.CENTER;
			constr.gridy = GridBagConstraints.RELATIVE;
			constr.gridx=1;

			Dimension tempDimension = new Dimension(1366,508), turnDimension = new Dimension(1366,80);
			mapArea.setMinimumSize(tempDimension);
			mapArea.setPreferredSize(tempDimension);
			mapArea.setSize(tempDimension);
			Image interactive = ImageIO.read(new FileInputStream(settings.get("matchpanel.interactive.background.image.path")));
			turnInfo = new RoundInformationPanel016(this,settings, interactive);
			turnInfo.setMinimumSize(turnDimension);
			turnInfo.setMaximumSize(turnDimension);
			add(turnInfo,constr);
			
			add(mapArea,constr);
			
			characterInformationPanel = new CharacterInformationContainerPanel016(mainFrame,matchManager,cache,settings);
			this.add(characterInformationPanel,constr);
			painter.settingUp(128, 128, 128, 64, size.width/2, 0);
			endMatchDialog = new EndMatchDialog(mainFrame, settings, cache);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	public MatchPanel(final long delay, SpriteSheetCache cache, it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.Map arena, MatchManager matchManager,MainFrame mainFrame, PrePlayMatchPanel parent)
	{
		super(delay,CONFIGURATION_FILE);
		this.mainFrame = mainFrame;
		poppedEndMatch = false;
//		System.out.println("!!!!! --- START MATCH PANEL --- !!!!");
		IniLoader loader = new IniLoader(new HashMap<String,String>());
		try 
		{
			this.matchManager = matchManager;
			
			GraphicEventManager.getInstance().addListener(this, CharacterClickEvent.class);
			GraphicEventManager.getInstance().addListener(this, ClickedMapCellEvent.class);

			EventManager.getInstance().addListener(this, new NotEnoughtCharacterEvent());
			EventManager.getInstance().addListener(this, new InvalidPointSettingEvent(false));
			EventManager.getInstance().addListener(this, new MovementEvent(null,0,0,0,0));
			EventManager.getInstance().addListener(this, new AttackEvent(false, false, null, null, null, 0.0f));
			EventManager.getInstance().addListener(this, new SelectedCharacterEvent(null, 0, 0, 0));
			EventManager.getInstance().addListener(this, new SelectedAbilityEvent(null, 0));
			EventManager.getInstance().addListener(this, new NoActionEvent());
			EventManager.getInstance().addListener(this, new TurnEvent());
			EventManager.getInstance().addListener(this, new EndMatchEvent(null,null));
			
			loader.load(CONFIGURATION_FILE);
			Map<String,String> settings = loader.getContents();
//			start = System.currentTimeMillis();
			setBackground(OverallGUILayoutFactory.getInstance().getParsedColor(settings.get("matchpanel.background.color")));
			painter = new IsometricMatchPainter(cache, settings.get("matchpanel.maparea.texture.path")+File.separator+arena.getName()+File.separator+"iso"+File.separator, null,matchManager.getClientPlayer().getCharacters(), matchManager.getEnemy().getCharacters(), arena);
			painter.setting(EventManager.getInstance());
			mapArea = new MapAreaPanel(arena, settings, null, painter);
			mapArea.addMouseMotionListener(new MouseMotionListener() {
				
				@Override
				public void mouseMoved(MouseEvent arg0) 
				{
					Point punto = new Point();
					painter.coordinates(arg0.getX(), arg0.getY(), 128, punto);
					painter.getAbilityCircle().setCenterRow(punto.x);
					painter.getAbilityCircle().setCenterColumn(punto.y);
//					System.out.println("!!!! "+arg0.getX()+" "+arg0.getY()+" ---> "+punto.getX()+" "+punto.getY());
					
				}
				
				@Override
				public void mouseDragged(MouseEvent arg0) {
					// TODO Auto-generated method stub
					
				}
			});
			turnDialog = new TurnDialog(mainFrame,settings);
			mapArea.setOpaque(false);
			Dimension size = mainFrame.getSize();
			this.setSize(size);
			setMinimumSize(size);
			GridBagLayout centerPaneLayout = new GridBagLayout();
			setLayout(centerPaneLayout);

			GridBagConstraints constr = new GridBagConstraints();
			constr.anchor = GridBagConstraints.CENTER;
			constr.gridy = GridBagConstraints.RELATIVE;
			constr.gridx=1;

			Dimension tempDimension = new Dimension(1366,508), turnDimension = new Dimension(1366,80);
			mapArea.setMinimumSize(tempDimension);
			mapArea.setPreferredSize(tempDimension);
			mapArea.setSize(tempDimension);
			Image interactive = ImageIO.read(new FileInputStream(settings.get("matchpanel.interactive.background.image.path")));
			turnInfo = new RoundInformationPanel016(this,settings, interactive);
			turnInfo.setMinimumSize(turnDimension);
			turnInfo.setMaximumSize(turnDimension);
			add(turnInfo,constr);
			
			add(mapArea,constr);
			
			characterInformationPanel = new CharacterInformationContainerPanel016(mainFrame,matchManager,cache,settings);
			this.add(characterInformationPanel,constr);
			painter.settingUp(128, 128, 128, 64, size.width/2, 0);
			endMatchDialog = new EndMatchDialog(mainFrame, settings, cache);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.guilayer.AnimatedPanel#updateScene()
	 */
	@Override
	protected void updateScene() 
	{
		if(matchManager.isMatchRunning())
		{
			turnDialog.update();
			matchManager.update();
			turnInfo.update(matchManager);
		}
		else
		{
			if(poppedEndMatch && painter.didAll())
			{
				System.out.println("MATCH FINITO NEED SWITCH");
				endMatchDialog.setMinimumSize(new Dimension(500, 500));
				endMatchDialog.setVisible(true);
				endMatchDialog.requestFocus();
				setReady(false);
			}
		}
		mapArea.updateMapGUI();
	}

	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.guilayer.AnimatedPanel#load(java.lang.String)
	 */
	@Override
	protected void load(String from) 
	{
		IniLoader fileLoader = new IniLoader(new HashMap<String,String>());
		Map<String,String> map = null;
		try {
			fileLoader.load(from);
			map = fileLoader.getContents();
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.guilayer.AnimatedPanel#settingScene()
	 */
	@Override
	protected void settingScene() {
		// TODO Auto-generated method stub

	}

	@Override
	public void notify(GenericEvent event) 
	{
		float idEvent = event.getGUID();
		
		if(listening)
		{
		if(idEvent == InvalidPointSettingEvent.GUID)
		{
			InvalidPointSettingEvent invalidPoint = (InvalidPointSettingEvent) event;
			System.out.println("INVALID QUALCOSA");
////			
			if(invalidPoint.isInvalidSource())
			{
				characterInformationPanel.reset();
			}
			else
			{
//				System.out.println("attuale "+characterInformationPanel.getActualCharacter().getName());
				matchManager.getClientPlayer().getActions().setNoAction();
//				characterInformationPanel.reset();
//				painter.setAbility(false);
//				painter.setSourceCirclePoint(null);
//				characterInformationPanel.setReady(false);
				characterInformationPanel.setActualCharacter(actor, true);
			}
		}
		else if(//idEvent == AttackEvent.GLOBALLY_UNIQUE_IDENTIFIER 
				//|| idEvent == MovementEvent.GUID 
				/*||*/ idEvent == NoActionEvent.GUID
				|| idEvent == EndActionEvent.GUID)
		{
//			boolean t = idEvent == AttackEvent.GLOBALLY_UNIQUE_IDENTIFIER;
//			System.out.println("CHIAMATO IL RESET "+t);
			characterInformationPanel.reset();
			painter.setAbility(false);
			painter.setSourceCirclePoint(null);
			characterInformationPanel.setReady(false);
		}else if(idEvent == SelectedCharacterEvent.GUID)
		{
			SelectedCharacterEvent selectedEvent = (SelectedCharacterEvent)event;
			painter.setSourceCirclePoint(selectedEvent.getCircleInfo());
			painter.getAbilityCircle().setRadius(0);
			actor = selectedEvent.getCharacter();
			System.out.println("hello im here");
//			selected = true;
//			pawnCircle = selectedEvent.getCircleInfo();
		}else if(idEvent == SelectedAbilityEvent.GUID)
		{
			SelectedAbilityEvent abilityEvent = (SelectedAbilityEvent) event;
			painter.setAbility(true);
			painter.getAbilityCircle().setRadius(abilityEvent.getRadius());
//			System.out.println(painter.getAbilityCircle().getRadius());
		}
		}
		if(idEvent == TurnEvent.GUID)
		{
			System.out.println("TURN EVENT");
			if(matchManager.getCurrentPlayer() == matchManager.getClientPlayer())
			{
//				System.out.println("TOCCA AL GIOCATORE CLIENT (GUI)");
				listening = true;
				turnInfo.changeTurn(true);
				turnDialog.setBackground(true);
			}else
			{
				listening = false;
				actor = null;
				turnDialog.setBackground(false);
				turnInfo.changeTurn(false);
			
			}
			turnDialog.setVisible(true);
//			turnDialog.requestFocus();
			
		}else if(idEvent == EndMatchEvent.GUID)
		{
			turnDialog.setVisible(false);
			turnDialog.dispose();
			try 
			{
			EndMatchEvent eme = (EndMatchEvent)event;
			boolean win = eme.getWinnerName().equalsIgnoreCase(matchManager.getClientPlayer().getNickname());
			endMatchDialog.set(win,matchManager.getClientPlayer().getNickname(),matchManager.getClientPlayer().getCharacters());
			} catch (InvalidFileException e) 
			{
				// This is not possible because images have been loaded before.
				e.printStackTrace();
			}
			poppedEndMatch = true;
			EventManager.getInstance().removeListener(this, new NotEnoughtCharacterEvent());
			EventManager.getInstance().removeListener(this, new InvalidPointSettingEvent(false));
			EventManager.getInstance().removeListener(this, new MovementEvent(null,0,0,0,0));
			EventManager.getInstance().removeListener(this, new AttackEvent(false, false, null, null, null, 0.0f));
			EventManager.getInstance().removeListener(this, new SelectedCharacterEvent(null, 0, 0, 0));
			EventManager.getInstance().removeListener(this, new SelectedAbilityEvent(null, 0));
			EventManager.getInstance().removeListener(this, new NoActionEvent());
			EventManager.getInstance().removeListener(this, new TurnEvent());
			EventManager.getInstance().removeListener(this, new EndMatchEvent(null,null));
			
			painter.dispose();
			
		}
		
	}

	@Override
	public void notify(GraphicEvent event) 
	{
		if(event instanceof ClickedMapCellEvent)
		{
			ClickedMapCellEvent clickEvent = (ClickedMapCellEvent) event;
			if(characterInformationPanel.isReady())
				matchManager.getCurrentPlayer().getActions().addActionInfo(new ActionCoordinateInfo(clickEvent.getRow(),clickEvent.getColumn()));
		}
		else if(event instanceof CharacterClickEvent)
		{
			CharacterClickEvent clickCharacter = (CharacterClickEvent) event;
			matchManager.getCurrentPlayer().getActions().addActionInfo(new ActionCoordinateInfo(clickCharacter.getClickedChar().getRow(), clickCharacter.getClickedChar().getColumn()));
			boolean allied = matchManager.getClientPlayer().getCharacters().contains(clickCharacter.getClickedChar());
			characterInformationPanel.setActualCharacter(clickCharacter.getClickedChar(), allied);
		}
	}
	
}
